package com.qf.abilit.gateway.filter;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.qf.redpack.base.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;

/**
 * 抢红包过滤器
 */
@Component
public class RobPackFilter extends AbstractGatewayFilterFactory {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    // 随机  最大金额 份数
    // 固定  份数 每份的金额

    private String robLua = """
            --接收参数 红包ID 用户ID
            local rid = KEYS[1]
            local uid = ARGV[1]
            --红包数据的key  lua脚本中用..拼接字符串
            local redKey =  "redpack:"..rid
            
            --判断红包数据是否存在
            local isExists = redis.call('exists', redKey)
            if isExists == 0 then
               --红包数据不存在
               return -1
            end
            
            --判断当前用户是否抢过该红包
            local isRob = redis.call("hexists", redKey, "uid"..uid)
            if isRob == 1 then
               --该用户已经抢过该红包
               return -2
            end
            
            --获取红包数据  
            local redArray = redis.call("hmget", redKey, "money", "count", "type")
            local money = tonumber(redArray[1])
            local count = tonumber(redArray[2])
            local type = tonumber(redArray[3])
            
            --判断红包是否已经抢完
            if count == 0 then
                --红包已经抢完
                return -3
            end
            
            --抢到的金额
            local robMoney = 0
            --是否为最后一个红包
            if count == 1 then
               --最后一个红包
               robMoney = money
            else
                --判断红包类型
                if type == 0 then 
                   --固定红包
                   robMoney = money / count   
                else
                   --随机红包 
                   robMoney = math.random(money / count * 2 - 1)
                end
            end
            
            --修改红包的数据
            redis.call("hset", redKey, "money", money - robMoney, "count", count - 1)
            --记录抢到的用户信息
            redis.call("hset", redKey, "uid"..uid, robMoney)
            --将抢到的金额返回
            return robMoney
            """;

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            System.out.println("抢红包的请求已经拦截！");

            //获取红包ID 和 用户ID
            ServerHttpRequest request = exchange.getRequest();
            String rid = request.getQueryParams().getFirst("rid");
            String uid = request.getQueryParams().getFirst("uid");

            //抢红包的逻辑
            long result = redisTemplate.execute(new DefaultRedisScript<>(robLua, Long.class),
                    ListUtil.of(rid),
                    uid);

            R r = R.succ();
            if (result > 0) {
                //抢到红包
                //单位转换
                double robMoney = BigDecimal.valueOf(result)
                        .divide(new BigDecimal(100), 2, RoundingMode.DOWN)
                        .doubleValue();
                r.setData(robMoney);
                //将抢到的红包金额 通过Kafka发送给红包服务，保存到数据库中
                Map<Object, Object> map = MapUtil.builder()
                        .put("rid", rid)
                        .put("uid", uid)
                        .put("robMoney", robMoney)
                        .build();
                kafkaTemplate.send("red-topic", JSONUtil.toJsonStr(map));

            } else {
                //没有抢到红包
                if (result == -1){
                    r.setMsg("红包信息有误！");
                } else if (result == -2) {
                    r.setMsg("你已经抢过红包了！");
                } else if (result == -3) {
                    r.setMsg("很遗憾，红包已经抢完了！");
                }
            }
            
            //将R对象直接响应给客户端
            ServerHttpResponse response = exchange.getResponse();
            DataBuffer dateBuffer = response.bufferFactory().wrap(JSONUtil.toJsonStr(r).getBytes());
            return response.writeWith(Mono.just(dateBuffer));
        };
    }

    @Override
    public String name() {
        return "robfilter";
    }

//    public static void main(String[] args) {
//        int money = 11;
//        int count = 10;
//
////        int c = count;
////        for (int i = 0; i < c; i++) {
////            int robMoney = ((int)(Math.random() * (money - count + 1))) + 1;
////            money -= robMoney;
////            count--;
////            System.out.println("第" + (i+1) + "个人抢走了：" + robMoney + "分");
////        }
//
//        //二倍均值法
//        // 1 ~ (money / count) * 2 //二倍均值法
//        // 第1个人：1 ~ 200 平均抢100
//        // 第2个人：1 ~ 200 平均抢100
//        int c = count;
//        int sum = 0;
//        for (int i = 0; i < c; i++) {
//            int robMoney = 0;
//            if (count != 1) {
//                robMoney = ((int) (Math.random() * (money / count * 2 - 1))) + 1;
//            } else {
//                //最后一个人 抢走剩余所有的金额
//                robMoney = money;
//            }
//            money -= robMoney;
//            count--;
//            System.out.println("第" + (i + 1) + "个人抢走了：" + robMoney + "分");
//            sum += robMoney;
//        }
//
//        System.out.println("抢到金额的累加：" + sum);
//
//    }
}
